// 草图 - 阵列
import {
  BaseCommand,
  CommandDialog,
  CommandDialogPlacement,
  EventsRes,
  ICurve,
  KEYBOARD_KEY,
  ObjInfo,
} from '@amcax/base';
import { ctx2 } from '@app-cad/module';

import i18n from '@app-cad/common/utils/i18next';

import {
  basicSketchIds,
  renderSketch,
  sketchPreview,
} from '@app-cad/common/utils';
import { wsApi } from '@app-cad/server';
import { RJSFSchema, UiSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';
import { useEffect, useState } from 'react';
import { Vector2 } from 'three-legacy';
import {
  SKETCH_CENTEREVENTS,
  sketchEventCenter,
} from '../../../events/SketchEventCenter';
import { PickInputForFocus2D } from '@app-cad/common/components/command-form/auto-focus/pick-input';
import { CommandFormWrapper } from '@app-cad/common/components/command-form';
import { NumberInputFormat } from '@app-cad/common/components/command-form/constants';
import { NonDialogPickableCommandForm } from '@app-cad/common/components/command-form/pickable';

interface ArrayDialogProps {
  title: string;
  placement: CommandDialogPlacement;
  props: ObjInfo;
  onClose: () => void;
}
function ArrayCommand({ onClose, title }: ArrayDialogProps) {
  const sketchId = sketchEventCenter().getSketchInfo().sketchId;
  const [number, setNumber] = useState(2);
  const [distance, setDistance] = useState(3);
  const [reverse, setReverse] = useState(false);
  const [patternValue, setPatternValue] = useState([]);
  const [directionValue, setDirectionValue] = useState([]);
  // 这里用于获取方向的数据计算向量传到后端
  const [directionData, setDirectionData] = useState([]);
  const formItemLayout = {
    labelCol: { span: 4 },
    wrapperCol: { span: 16 },
  };
  const schema: RJSFSchema = {
    type: 'object',
    properties: {
      count: {
        type: 'number',
        title: '数量',
        default: 2,
        maximum: 100,
        format: NumberInputFormat.Integer,
      },
      distance: {
        type: 'number',
        title: '间距',
        default: 3,
        format: NumberInputFormat.Length,
      },
      reverse: {
        type: 'boolean',
        title: '反向',
        default: false,
      },
    },
  };
  const uiSchema: UiSchema = {
    'ui:options': {
      classNames: 'cmd-sketch-form-array',
    },
  };
  useEffect(() => {
    sketchEventCenter()
      .setState('array')
      .on(SKETCH_CENTEREVENTS.KEYUP, onKeyUp);
    return () => {
      sketchEventCenter().setDefault().off(SKETCH_CENTEREVENTS.KEYUP, onKeyUp);
      ctx2.cadScene.assisGroup.clear();
    };
  }, []);
  const onKeyUp = (e: EventsRes<KeyboardEvent>) => {
    if (e.key === KEYBOARD_KEY.ESC) {
      onClose();
    }
  };

  useEffect(() => {
    if (patternValue.length > 0 && directionValue.length > 0) {
      ctx2.cadScene.assisGroup.clear();
      preview(number, distance, reverse);
    } else {
      ctx2.cadScene.assisGroup.clear();
      ctx2.viewer.requestRender();
    }
  }, [patternValue, directionValue, number, distance, reverse]);
  const onPatternData = (ids: string[], picked: ICurve[]) => {
    if (picked.length === 0) {
      setPatternValue([]);
    } else {
      ctx2.cadScene.assisGroup.clear();
      setPatternValue(ids);
    }
  };
  const preview = async (number, distance, reverse) => {
    const start: Vector2 = new Vector2(
      directionData[0].vertices[0][0],
      directionData[0].vertices[0][1],
    );
    const end: Vector2 = new Vector2(
      directionData[0].vertices[1][0],
      directionData[0].vertices[1][1],
    );
    const excludeValue = basicSketchIds;
    const patternValues = patternValue.filter((item) => {
      return !excludeValue.includes(item);
    });
    const direction: Vector2 = new Vector2().subVectors(end, start);
    const res = await wsApi.arraySketchCurve(
      sketchId,
      patternValues,
      number,
      direction,
      distance,
      null,
      null,
      true,
      reverse,
    );
    sketchPreview(res.curves);
  };
  const onDirectionData = (ids: string[], picked: ICurve[]) => {
    if (picked.length === 0) {
      setDirectionValue([]);
    } else if (picked && picked[0].type === 'Line') {
      ctx2.cadScene.assisGroup.clear();
      setDirectionValue(ids);
      setDirectionData(picked);
    }
  };
  const onSubmit = async (formData) => {
    const start: Vector2 = new Vector2(
      directionData[0].vertices[0][0],
      directionData[0].vertices[0][1],
    );
    const end: Vector2 = new Vector2(
      directionData[0].vertices[1][0],
      directionData[0].vertices[1][1],
    );
    const excludeValue = basicSketchIds;
    const patternValues = patternValue.filter((item) => {
      return !excludeValue.includes(item);
    });
    const direction: Vector2 = new Vector2().subVectors(end, start);
    const res = await wsApi.arraySketchCurve(
      sketchId,
      patternValues,
      formData.count,
      direction,
      formData.distance,
      null,
      null,
      false,
      formData.reverse,
    );
    onClose();
    await renderSketch(sketchId, res);
    ctx2.cadScene.assisGroup.clear();
  };
  const onChange = async ({ count, distance, reverse }) => {
    // inputNumber 输入框小于合理值的时候，不显示预览
    if (!distance || distance < 1 || !count || count < 2) {
      ctx2.cadScene.assisGroup.clear();
      ctx2.viewer.requestRender();
    } else {
      if (directionData.length > 0 && patternValue.length > 0) {
        await preview(count, distance, reverse);
      }
      setNumber(count);
      setDistance(distance);
      setReverse(reverse);
    }
  };
  return (
    <>
      <CommandDialog
        title={title}
        placement='topLeft'
        className='sketchDialog'
        onClose={onClose}
      >
        <CommandFormWrapper>
          <PickInputForFocus2D
            value={patternValue}
            onPick={onPatternData}
            controlled
            isMulti
            className='pick-input-2d'
            placeholder='阵列实体'
            autoFocus
          />
          <PickInputForFocus2D
            value={directionValue}
            onPick={onDirectionData}
            controlled
            className='pick-input-2d'
            placeholder='阵列方向'
          />
          <NonDialogPickableCommandForm
            formContext={formItemLayout}
            schema={schema}
            extraUiSchema={uiSchema}
            validator={validator}
            onSubmit={onSubmit}
            onChange={onChange}
            showCancel={false}
            submitText='执行'
          />
        </CommandFormWrapper>
      </CommandDialog>
    </>
  );
}

export const cmdArray: BaseCommand = {
  id: 'CmdArray',
  label: 'command.linear-array',
  icon: 'commands/sketch/rectangular-pattern',
  group: 'sketch',
  create: (label: string, onClose: () => void, props) => (
    <ArrayCommand
      title={i18n.t(label)}
      onClose={onClose}
      props={props}
      placement='topLeft'
    />
  ),
};
